// arch-tag: a7027152-b6e8-4e3c-9099-39f35043ad73
package de.yvert.jingle.impl.reader;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

import de.yvert.jingle.ImageReader;
import de.yvert.jingle.help.ConverterInputStream;
import de.yvert.jingle.ldr.LdrImage2D;

public class ImageReader_tga implements ImageReader
{

public ImageReader_tga()
{/*OK*/}

private LdrImage2D load(ConverterInputStream in) throws IOException
{
	int idlength = in.readUnsignedByte();
	int cmaptype = in.readUnsignedByte();
	if (idlength != 0) throw new IOException("Unfinished!");
	if (cmaptype != 0) throw new IOException("Unfinished!");
	
	int imagetype = in.readUnsignedByte();
	if ((imagetype != 2) && (imagetype != 10))
		throw new IOException("Unfinished: unknown image type \""+imagetype+"\"!");
	
	in.skipBytes(5);
	in.readUnsignedShort(); // read x-origin
	in.readUnsignedShort(); // read y-origin
	
	int width = in.readUnsignedShort();
	int height = in.readUnsignedShort();
	
	int bitsperpixel = in.readUnsignedByte();
	if (bitsperpixel != 32)
		throw new IOException("Unfinished: unknown # of bpp \""+bitsperpixel+"\"!");
	
	// |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
	// | reserv. | order   |    # alpha bits   |
	int descriptor = in.readUnsignedByte();
	if ((descriptor != 8) && (descriptor != 0) && (descriptor != 40) && (descriptor != 32))
		throw new IOException("Unfinished: unknown descriptor \""+descriptor+"\"!");
	
	int pixelOrder = (descriptor >> 4) & 0x3;
	
	// Skip image identification and colormap
	// both not existant when the above doesn't throw an exception
	
	LdrImage2D result = new LdrImage2D(width, height);
	if (imagetype == 2)
	{
		// direct BGRA data
		byte[] data = new byte[width*height*4];
		in.readFully(data);
		result.decodeBGRA(data);
	}
	else if (imagetype == 10)
	{
		// runlength encoded BGRA data
		for (int y = 0; y < height; y++)
		{
			int x = 0;
			while (x < width)
			{
				int code = in.readUnsignedByte();
				if ((code & 0x80) != 0)
				{
					code = (code & 0x7F) + 1;
					int value = in.readInt();
					for (int i = 0; i < code; i++)
						result.setBGRAint(x++, y, value);
				}
				else
				{
					code = code+1;
					for (int i = 0; i < code; i++)
					{
						int value = in.readInt();
						result.setBGRAint(x++, y, value);
					}
				}
			}
		}
	}
	else
		throw new IOException("Internal error: invalid image type!");
	
	if (pixelOrder == 0) result.flipY();
	
	return result;
}

public LdrImage2D load(InputStream in) throws IOException
{
	ConverterInputStream cin = new ConverterInputStream(ConverterInputStream.LITTLE_ENDIAN, new BufferedInputStream(in));
	return load(cin);
}

}
